package com.xyf.sys.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.xyf.sys.config.MiniprogramConfig;
import com.xyf.sys.domain.ChannelConfig;
import com.xyf.sys.domain.Delivery;
import com.xyf.sys.domain.Order;
import com.xyf.sys.domain.User;
import com.xyf.sys.enums.DeliveryEnum;
import com.xyf.sys.mapper.OrderMapper;
import com.xyf.sys.mapper.UserMapper;
import com.xyf.sys.service.IDeliveryService;
import com.xyf.sys.service.IOrderService;
import com.xyf.sys.service.IUserService;
import com.xyf.sys.service.IWechatService;
import com.xyf.sys.util.R;
import com.xyf.sys.util.SignUtil;
import com.xyf.sys.util.WXBizMsgCrypt;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.w3c.dom.Document;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.xpath.XPathConstants;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.stream.Collectors;

import static com.xyf.sys.constant.CommonConstant.channelsConfigList;

/**
 * @Author R-H
 * @Date 2024/6/201738
 * @Description
 */
@RestController
@RequestMapping("/wechat")
@Slf4j
public class WechatMessageController {

    @Autowired
    private IWechatService wechatService;
    @Autowired
    private IUserService userService;
    @Autowired
    private UserMapper userMapper;
    @Value("${jd.serverUrl}")
    private String serverUrl;
    @Value("${jd.appKey}")
    private String appKey;
    @Value("${jd.appSecret}")
    private String appSecret;
    @Autowired
    private IDeliveryService deliveryService;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    @Qualifier("serveConfig")
    private MiniprogramConfig.MiniConfig serveConfig;

    /**
     * 微信消息处理
     */
    @RequestMapping(value = "/message", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void handleMessage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String method = request.getMethod();
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        if (RequestMethod.GET.toString().equalsIgnoreCase(method)) {
            String signature = request.getParameter("signature");
            String timestamp = request.getParameter("timestamp");
            String nonce = request.getParameter("nonce");
            String echostr = request.getParameter("echostr");
            log.info("signature[{}], timestamp[{}], nonce[{}], echostr[{}]", signature, timestamp, nonce, echostr);
            if (SignUtil.checkSignature("Tokenxxxx", signature, timestamp, nonce)) {
                log.info("数据源为微信后台，将echostr[{}]返回！", echostr);
                response.getOutputStream().println(echostr);
            }
        } else {
            String contentType = request.getContentType();
            String toUserName = null;
            Long createTime = null;
            String msgType = null;
            String event = null;
            String fromUserName = null;
            if (contentType != null && contentType.contains("application/xml")) {
                Document document = XmlUtil.readXML(request.getReader());
                log.info("xml str {}", XmlUtil.toStr(document));
                toUserName = (String) XmlUtil.getByXPath("//xml/ToUserName", document, XPathConstants.STRING);
                createTime = Long.valueOf((String) XmlUtil.getByXPath("//xml/CreateTime", document, XPathConstants.STRING));
                msgType = (String) XmlUtil.getByXPath("//xml/MsgType", document, XPathConstants.STRING);
                event = (String) XmlUtil.getByXPath("//xml/Event", document, XPathConstants.STRING);
                fromUserName = (String) XmlUtil.getByXPath("//xml/FromUserName", document, XPathConstants.STRING);
                log.info("wechat message body {}", XmlUtil.toStr(document));
            } else if (contentType != null && contentType.contains("application/json")) {
                String line;
                StringBuffer buf = new StringBuffer();
                while ((line = request.getReader().readLine()) != null) {
                    buf.append(line);
                }
                log.info("body {}", buf.toString());
                JSONObject jsonObject = JSONObject.parseObject(buf.toString());
                toUserName = jsonObject.getString("ToUserName");
                createTime = jsonObject.getLong("CreateTime");
                msgType = jsonObject.getString("MsgType");
                event = jsonObject.getString("Event");
                fromUserName = jsonObject.getString("FromUserName");
            }
            log.info("CreateTime:{}", createTime);
            log.info("MsgType:{}", msgType);
            String wxopenid = request.getHeader("X-WX-OPENID");
            log.info("X-WX-OPENID {}", wxopenid);
            String wxappid = request.getHeader("X-WX-APPID");
            log.info("X-WX-APPID {}", wxappid);
            String wxunionid = request.getHeader("X-WX-UNIONID");
            log.info("X-WX-UNIONID {}", wxunionid);
            String openid = request.getHeader("X-WX-FROM-OPENID");
            log.info("X-WX-FROM-OPENID {}", openid);
            String appid = request.getHeader("X-WX-FROM-APPID");
                log.info("X-WX-FROM-APPID {}", appid);
            String unionid = request.getHeader("X-WX-FROM-UNIONID");
            log.info("X-WX-FROM-UNIONID {}", unionid);
            if ("text".equals(msgType)) {
            } else if ("image".equals(msgType)) {
            } else if ("event".equals(msgType)) {
                if ("subscribe".equals(event)) {
                    log.info("FromUserName:{}", fromUserName);
                    if (StringUtils.isBlank(unionid)){
                        String accessToken = wechatService.getAccessToken(serveConfig.getAppid(), serveConfig.getSecret());
                        JSONObject userInfo = wechatService.getUserInfo(accessToken, fromUserName);
                        unionid = userInfo.getString("unionid");
                        openid = userInfo.getString("openid");
                    }
                    User user = userService.getUser(fromUserName);
                    if (user == null) {
                        userService.create(openid, unionid, appid);
                    } else {
                        user.setUnionid(unionid);
                        user.setAppid(appid);
                        userMapper.updateByPrimaryKeySelective(user);
                    }
                    wechatService.replyFollowMessage("感谢关注", fromUserName, appid);
                }
                if ("unsubscribe".equals(event)) {
                }
            }
            response.getWriter().write("success");
        }
    }

    /**
     * 微信消息处理
     */
    @RequestMapping(value = "/callback", method = RequestMethod.GET)
    @ResponseBody
    public Object callback(@RequestParam String code, HttpServletRequest request) {
        // https://oauth.jdl.com/oauth/authorize?client_id=&redirect_uri=/api/wechat/callback&response_type=code
        log.info("callback body {}", code);
        if (StringUtils.isNotBlank(code)) {
            String response = HttpUtil.get("https://oauth.jdl.com/oauth/token?code=" + code + "&client_secret=" + appSecret + "&client_id=" + appKey);
            log.info("jd token {}", response);
            if (StringUtils.isNotBlank(response)) {
                Delivery config = deliveryService.getConfig(DeliveryEnum.JD.toString());
                JSONObject jsonObject = JSONObject.parseObject(response);
                String accessToken = jsonObject.getString("accessToken");
                String refreshToken = jsonObject.getString("refreshToken");
                String accessExpire = jsonObject.getString("accessExpire");
                config.setAuthCode(accessToken);
                config.setRemark(jsonObject.toJSONString());
                config.setUpdateTime(new Date());
                deliveryService.update(config);
            }
        }
        return R.ok(StringUtils.EMPTY);
    }


    /**
     * 微信消息处理
     */
    @RequestMapping(value = "/channels/{channelId}", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void channels(@PathVariable String channelId,  HttpServletRequest request, HttpServletResponse response) throws IOException {
        String method = request.getMethod();
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        ChannelConfig channelConfig = userService.findChannelConfig(channelId);
        if (RequestMethod.GET.toString().equalsIgnoreCase(method)) {
            String signature = request.getParameter("signature");
            String timestamp = request.getParameter("timestamp");
            String nonce = request.getParameter("nonce");
            String echostr = request.getParameter("echostr");
            log.info("signature[{}], timestamp[{}], nonce[{}], echostr[{}]", signature, timestamp, nonce, echostr);
            if (SignUtil.checkSignature(channelConfig.getToken(), signature, timestamp, nonce)) {
                log.info("数据源为微信后台，将echostr[{}]返回！", echostr);
                response.getOutputStream().println(echostr);
            }
        } else {
            try {
                String line;
                StringBuffer buf = new StringBuffer();
                while ((line = request.getReader().readLine()) != null) {
                    buf.append(line);
                }
                log.info("body {}", buf.toString());
                JSONObject jsonObject = JSONObject.parseObject(buf.toString());
                String encrypt = jsonObject.getString("Encrypt");
                WXBizMsgCrypt pc = new WXBizMsgCrypt(channelConfig.getToken(), channelConfig.getEncodingAesKey(), "wx9c07d357a94b821a");
                // 微信加密签名
                String msgSignature = request.getParameter("msg_signature");
                log.info("msgSignature = " + msgSignature);
                // 时间戳
                String timestamp = request.getParameter("timestamp");
                log.info("timestamp = " + timestamp);
                // 随机数
                String nonce = request.getParameter("nonce");
                log.info("nonce = " + nonce);
                String respXml = pc.decryptMsg(msgSignature, timestamp, nonce, encrypt);
                log.info("crypt xml str {}", respXml);
                JSONObject data = JSONObject.parseObject(respXml);
                if ("event".equalsIgnoreCase(data.getString("MsgType"))) {
                    if ("channels_ec_order_new".equalsIgnoreCase(data.getString("Event"))) {
                        String fromUserName = data.getString("FromUserName");
                        JSONObject order_info = data.getJSONObject("order_info");
                        String order_id = order_info.getString("order_id");
                        String accessToken = wechatService.getAccessToken("wxd1c92a8a56e4b777", "d35ba56c9ac0b24879c0ce6ae10b4f52");
                        JSONObject orderInfo = wechatService.queryChannelsOrder(order_id, accessToken);
                        log.info("channel order info {}", orderInfo);
//                        JSONObject userInfo = wechatService.getUserInfo(accessToken, fromUserName);
//                        log.info("order user info {}", userInfo);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            response.getWriter().write("success");
        }
    }


    /**
     * 微信小程序发货信息管理 相关消息推送
     */
    @RequestMapping(value = "/trackingMessage", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void trackingMessage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String method = request.getMethod();
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        if (RequestMethod.GET.toString().equalsIgnoreCase(method)) {
            String signature = request.getParameter("signature");
            String timestamp = request.getParameter("timestamp");
            String nonce = request.getParameter("nonce");
            String echostr = request.getParameter("echostr");
            log.info("signature[{}], timestamp[{}], nonce[{}], echostr[{}]", signature, timestamp, nonce, echostr);
            if (SignUtil.checkSignature("", signature, timestamp, nonce)) {
                log.info("数据源为微信后台，将echostr[{}]返回！", echostr);
                response.getOutputStream().println(echostr);
            }
        } else {
            try {
                String line;
                StringBuffer buf = new StringBuffer();
                while ((line = request.getReader().readLine()) != null) {
                    buf.append(line);
                }
                log.info("body {}", buf.toString());
                JSONObject data = JSONObject.parseObject(buf.toString());
                if ("event".equalsIgnoreCase(data.getString("MsgType"))) {
                    if ("trade_manage_remind_access_api".equalsIgnoreCase(data.getString("Event"))) {
                        String fromUserName = data.getString("FromUserName");
                        String order_info = data.getString("msg");
                    }
                    if ("trade_manage_remind_shipping".equalsIgnoreCase(data.getString("Event"))) {
                        String fromUserName = data.getString("FromUserName");
                        String transaction_id = data.getString("transaction_id");
                    }
                    if ("trade_manage_order_settlement".equalsIgnoreCase(data.getString("Event"))) {
                        String fromUserName = data.getString("FromUserName");
                        String transaction_id = data.getString("transaction_id");
                        String confirm_receive_method = data.getString("confirm_receive_method");
                        Long confirm_receive_time = data.getLong("confirm_receive_time");
                        if (StringUtils.isNotBlank(confirm_receive_method)){
                            Order order = orderService.getByTransactionId(transaction_id);
                            order.setDeliveryStatus(2);
                            order.setReceiveTime(DateTime.of(confirm_receive_time * 1000).toJdkDate());
                            orderMapper.updateByPrimaryKeySelective(order);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            response.getWriter().write("success");
        }
    }
}
